home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 4 / QRZ Ham Radio Callsign Database - Volume 4.iso / files / dsp / 56ktools / dspkgctr.z / dspkgctr / gcc / rtl.c < prev    next >
C/C++ Source or Header  |  1992-06-08  |  20KB  |  835 lines

  1. /* Allocate, read and print RTL for C-Compiler
  2.    Copyright (C) 1987, 1988 Free Software Foundation, Inc.
  3.  
  4.    $Id: rtl.c,v 1.8 91/10/23 17:02:56 pete Exp $
  5.  
  6. This file is part of GNU CC.
  7.  
  8. GNU CC is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 1, or (at your option)
  11. any later version.
  12.  
  13. GNU CC is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. GNU General Public License for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with GNU CC; see the file COPYING.  If not, write to
  20. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  21.  
  22.  
  23. #include "config.h"
  24. #include <ctype.h>
  25. #include <stdio.h>
  26. #include "rtl.h"
  27.  
  28. #include "obstack.h"
  29. #define    obstack_chunk_alloc    xmalloc
  30. #define    obstack_chunk_free    free
  31. extern int xmalloc ();
  32. extern void free ();
  33.  
  34. /* Obstack used for allocating RTL objects.
  35.    Between functions, this is the permanent_obstack.
  36.    While parsing and expanding a function, this is maybepermanent_obstack
  37.    so we can save it if it is an inline function.
  38.    During optimization and output, this is temporary_obstack.  */
  39.  
  40. extern struct obstack *rtl_obstack;
  41.  
  42. #define MIN(x,y) ((x < y) ? x : y)
  43.  
  44. extern long ftell();
  45.  
  46. /* Indexed by rtx code, gives number of operands for an rtx with that code.
  47.    Does NOT include rtx header data (code and links).
  48.    This array is initialized in init_rtl.  */
  49.  
  50. int rtx_length[NUM_RTX_CODE + 1];
  51.  
  52. /* Indexed by rtx code, gives the name of that kind of rtx, as a C string.  */
  53.  
  54. #define DEF_RTL_EXPR(ENUM, NAME, FORMAT)   NAME ,
  55.  
  56. char *rtx_name[] = {
  57. #include "rtl.def"        /* rtl expressions are documented here */
  58. };
  59.  
  60. #undef DEF_RTL_EXPR
  61.  
  62. /* Indexed by machine mode, gives the name of that machine mode.
  63.    This name does not include the letters "mode".  */
  64.  
  65. #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  NAME,
  66.  
  67. char *mode_name[] = {
  68. #include "machmode.def"
  69. };
  70.  
  71. #undef DEF_MACHMODE
  72.  
  73. /* Indexed by machine mode, gives the length of the mode, in bytes.
  74.    GET_MODE_CLASS uses this.  */
  75.  
  76. #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  CLASS,
  77.  
  78. enum mode_class mode_class[] = {
  79. #include "machmode.def"
  80. };
  81.  
  82. #undef DEF_MACHMODE
  83.  
  84. /* Indexed by machine mode, gives the length of the mode, in bytes.
  85.    GET_MODE_SIZE uses this.  */
  86.  
  87. #if defined( DSP56000 )
  88. #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  \
  89.   (SIZE),
  90. #else
  91. #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  \
  92.   (SIZE*UNITS_PER_WORD+3)/4,
  93. #endif
  94.  
  95. int mode_size[] = {
  96. #include "machmode.def"
  97. };
  98.  
  99. #undef DEF_MACHMODE
  100.  
  101. /* Indexed by machine mode, gives the length of the mode's subunit.
  102.    GET_MODE_UNIT_SIZE uses this.  */
  103.  
  104. #if defined( DSP56000 )
  105. #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  \
  106.   (UNIT),
  107. #else
  108. #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  \
  109.   (UNIT*UNITS_PER_WORD+3)/4,
  110. #endif
  111. int mode_unit_size[] = {
  112. #include "machmode.def"        /* machine modes are documented here */
  113. };
  114.  
  115. #undef DEF_MACHMODE
  116.  
  117. /* Indexed by machine mode, gives next wider natural mode
  118.    (QI -> HI -> SI -> DI, etc.)  Widening multiply instructions
  119.    use this.  */
  120.  
  121. #define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  \
  122.   (enum machine_mode) WIDER,
  123.  
  124. enum machine_mode mode_wider_mode[] = {
  125. #include "machmode.def"        /* machine modes are documented here */
  126. };
  127.  
  128. #undef DEF_MACHMODE
  129.  
  130. /* Indexed by rtx code, gives a sequence of operand-types for
  131.    rtx's of that code.  The sequence is a C string in which
  132.    each charcter describes one operand.  */
  133.  
  134. char *rtx_format[] = {
  135.   /* "*" undefined.
  136.          can cause a warning message
  137.      "0" field is unused (or used in a phase-dependent manner)
  138.          prints nothing
  139.      "i" an integer
  140.          prints the integer
  141.      "s" a pointer to a string
  142.          prints the string
  143.      "S" like "s", but optional:
  144.      the containing rtx may end before this operand
  145.      "e" a pointer to an rtl expression
  146.          prints the expression
  147.      "E" a pointer to a vector that points to a number of rtl expressions
  148.          prints a list of the rtl expressions
  149.      "u" a pointer to another insn
  150.          prints the uid of the insn.  */
  151.  
  152. #define DEF_RTL_EXPR(ENUM, NAME, FORMAT)   FORMAT ,
  153. #include "rtl.def"        /* rtl expressions are defined here */
  154. #undef DEF_RTL_EXPR
  155. };
  156.  
  157. /* Names for kinds of NOTEs and REG_NOTEs.  */
  158.  
  159. char *note_insn_name[] = { "NOTE_INSN_FUNCTION_BEG", "NOTE_INSN_DELETED",
  160.                "NOTE_INSN_BLOCK_BEG", "NOTE_INSN_BLOCK_END",
  161.                "NOTE_INSN_LOOP_BEG", "NOTE_INSN_LOOP_END",
  162.                "NOTE_INSN_FUNCTION_END", "NOTE_INSN_SETJMP",
  163.                "NOTE_INSN_LOOP_CONT" };
  164.  
  165. char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0",
  166.               "REG_EQUAL", "REG_RETVAL", "REG_LIBCALL",
  167.               "REG_NONNEG", "REG_ASM_LINE", "REG_ASM_FILE" };
  168.  
  169. /* Allocate an rtx vector of N elements.
  170.    Store the length, and initialize all elements to zero.  */
  171.  
  172. rtvec
  173. rtvec_alloc (n)
  174.      int n;
  175. {
  176.   rtvec rt;
  177.   int i;
  178.  
  179.   rt = (rtvec) obstack_alloc (rtl_obstack,
  180.                   sizeof (struct rtvec_def)
  181.                   + (( n - 1) * sizeof (rtunion)));
  182.  
  183.   /* clear out the vector */
  184.   PUT_NUM_ELEM(rt, n);
  185.   for (i=0; i < n; i++)
  186.     rt->elem[i].rtvec = NULL;    /* @@ not portable due to rtunion */
  187.  
  188.   return rt;
  189. }
  190.  
  191. /* Allocate an rtx of code CODE.  The CODE is stored in the rtx;
  192.    all the rest is initialized to zero.  */
  193.  
  194. rtx
  195. rtx_alloc (code)
  196.   RTX_CODE code;
  197. {
  198.   rtx rt;
  199.   register int nelts = GET_RTX_LENGTH (code);
  200.   register int length = sizeof (struct rtx_def)
  201.     + (nelts - 1) * sizeof (rtunion);
  202.  
  203.   rt = (rtx) obstack_alloc (rtl_obstack, length);
  204.  
  205. #if defined( DSP56000 ) || defined( DSP96000 )
  206.   /* guarentee that EVERYTHING is cleared */
  207.   bzero( (char*) rt, length );
  208. #else
  209.   * (int *) rt = 0;
  210. #endif
  211.   PUT_CODE (rt, code);
  212.  
  213.   return rt;
  214. }
  215.  
  216. /* Create a new copy of an rtx.
  217.    Recursively copies the operands of the rtx,
  218.    except for those few rtx codes that are sharable.  */
  219.  
  220. rtx
  221. copy_rtx (orig)
  222.      register rtx orig;
  223. {
  224.   register rtx copy;
  225.   register int i, j;
  226.   register RTX_CODE code;
  227.   register char *format_ptr;
  228.  
  229.   code = GET_CODE (orig);
  230.  
  231.   switch (code)
  232.     {
  233.     case REG:
  234.     case QUEUED:
  235.     case CONST_INT:
  236.     case CONST_DOUBLE:
  237.     case SYMBOL_REF:
  238.     case CODE_LABEL:
  239.     case PC:
  240.     case CC0:
  241.       return orig;
  242.     }
  243.  
  244.   copy = rtx_alloc (code);
  245.   PUT_MODE (copy, GET_MODE (orig));
  246.   copy->in_struct = orig->in_struct;
  247.   copy->volatil = orig->volatil;
  248.   copy->unchanging = orig->unchanging;
  249.   copy->integrated = orig->integrated;
  250. #if defined( DSP56000 )
  251.   /* added fields for DSP enhancements. */
  252.   copy->reload_subreg = orig->reload_subreg;
  253. #endif
  254. #if defined( DSP56000 ) || defined( DSP96000 )
  255.   copy->reload_generated = orig->reload_generated;
  256. #endif
  257.   
  258.   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
  259.  
  260.   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
  261.     {
  262.       switch (*format_ptr++)
  263.     {
  264.     case 'e':
  265.       XEXP (copy, i) = XEXP (orig, i);
  266.       if (XEXP (orig, i) != NULL)
  267.         XEXP (copy, i) = copy_rtx (XEXP (orig, i));
  268.       break;
  269.  
  270.     case 'E':
  271.       XVEC (copy, i) = XVEC (orig, i);
  272.       if (XVEC (orig, i) != NULL)
  273.         {
  274.           XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
  275.           for (j = 0; j < XVECLEN (copy, i); j++)
  276.         XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j));
  277.         }
  278.       break;
  279.  
  280.     default:
  281.       XINT (copy, i) = XINT (orig, i);
  282.       break;
  283.     }
  284.     }
  285.   return copy;
  286. }
  287.  
  288. /* Printing rtl for debugging dumps.  */
  289.  
  290. static FILE *outfile;
  291.  
  292. char spaces[] = "                                                                                                                                                                ";
  293.  
  294. static int sawclose = 0;
  295.  
  296. /* Print IN_RTX onto OUTFILE.  This is the recursive part of printing.  */
  297.  
  298. static void
  299. print_rtx (in_rtx)
  300.      register rtx in_rtx;
  301. {
  302.   static int indent;
  303.   register int i, j;
  304.   register char *format_ptr;
  305.  
  306.   if (sawclose)
  307.     {
  308.       fprintf (outfile, "\n%s",
  309.            (spaces + (sizeof spaces - indent * 2)));
  310.       sawclose = 0;
  311.     }
  312.  
  313.   if (in_rtx == 0)
  314.     {
  315.       fprintf (outfile, "(nil)");
  316.       sawclose = 1;
  317.       return;
  318.     }
  319.  
  320.   /* print name of expression code */
  321.   fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));
  322.  
  323.   if (in_rtx->in_struct)
  324.     fprintf (outfile, "/s");
  325.  
  326.   if (in_rtx->volatil)
  327.     fprintf (outfile, "/v");
  328.  
  329.   if (in_rtx->unchanging)
  330.     fprintf (outfile, "/u");
  331.  
  332.   if (in_rtx->integrated)
  333.     fprintf (outfile, "/i");
  334.  
  335.   if (GET_MODE (in_rtx) != VOIDmode)
  336.     {
  337.       /* Print REG_NOTE names for EXPR_LIST and INSN_LIST.  */
  338.       if (GET_CODE (in_rtx) == EXPR_LIST || GET_CODE (in_rtx) == INSN_LIST)
  339.     fprintf (outfile, ":%s", GET_REG_NOTE_NAME (GET_MODE (in_rtx)));
  340.       else
  341.     fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx)));
  342.     }
  343.  
  344.   format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx));
  345.  
  346.   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++)
  347.     switch (*format_ptr++)
  348.       {
  349.       case 'S':
  350.       case 's':
  351.     if (XSTR (in_rtx, i) == 0)
  352.       fprintf (outfile, " \"\"");
  353.     else
  354.       fprintf (outfile, " (\"%s\")", XSTR (in_rtx, i));
  355.     sawclose = 1;
  356.     break;
  357.  
  358.     /* 0 indicates a field for internal use that should not be printed.  */
  359.       case '0':
  360.     break;
  361.  
  362.       case 'e':
  363.     indent += 2;
  364.     if (!sawclose)
  365.       fprintf (outfile, " ");
  366.     print_rtx (XEXP (in_rtx, i));
  367.     indent -= 2;
  368.     break;
  369.  
  370.       case 'E':
  371.     indent += 2;
  372.     if (sawclose)
  373.       {
  374.         fprintf (outfile, "\n%s",
  375.              (spaces + (sizeof spaces - indent * 2)));
  376.         sawclose = 0;
  377.       }
  378.     fprintf (outfile, "[ ");
  379.     if (NULL != XVEC (in_rtx, i))
  380.       {
  381.         indent += 2;
  382.         if (XVECLEN (in_rtx, i))
  383.           sawclose = 1;
  384.  
  385.         for (j = 0; j < XVECLEN (in_rtx, i); j++)
  386.           print_rtx (XVECEXP (in_rtx, i, j));
  387.  
  388.         indent -= 2;
  389.       }
  390.     if (sawclose)
  391.       fprintf (outfile, "\n%s",
  392.            (spaces + (sizeof spaces - indent * 2)));
  393.  
  394.     fprintf (outfile, "] ");
  395.     sawclose = 1;
  396.     indent -= 2;
  397.     break;
  398.  
  399.       case 'i':
  400.     fprintf (outfile, " %d", XINT (in_rtx, i));
  401.     sawclose = 0;
  402.     break;
  403.  
  404.       /* Print NOTE_INSN names rather than integer codes.  */
  405.  
  406.       case 'n':
  407.     if (XINT (in_rtx, i) <= 0)
  408.       fprintf (outfile, " %s", GET_NOTE_INSN_NAME (XINT (in_rtx, i)));
  409.     else
  410.       fprintf (outfile, " %d", XINT (in_rtx, i));
  411.     sawclose = 0;
  412.     break;
  413.  
  414.       case 'u':
  415.     if (XEXP (in_rtx, i) != NULL)
  416.       fprintf(outfile, " %d", INSN_UID (XEXP (in_rtx, i)));
  417.     else
  418.       fprintf(outfile, " 0");
  419.     sawclose = 0;
  420.     break;
  421.  
  422.       default:
  423.     fprintf (stderr,
  424.          "switch format wrong in rtl.print_rtx(). format was: %c.\n",
  425.          format_ptr[-1]);
  426.     abort ();
  427.       }
  428.  
  429.   fprintf (outfile, ")");
  430.   sawclose = 1;
  431. }
  432.  
  433. /* Call this function from the debugger to see what X looks like.  */
  434.  
  435. void
  436. debug_rtx (x)
  437.      rtx x;
  438. {
  439.   outfile = stderr;
  440.   print_rtx (x);
  441.   fprintf (stderr, "\n");
  442. }
  443.  
  444. /* External entry point for printing a chain of insns
  445.    starting with RTX_FIRST onto file OUTF.
  446.    A blank line separates insns.
  447.  
  448.    If RTX_FIRST is not an insn, then it alone is printed, with no newline.  */
  449.  
  450. void
  451. print_rtl (outf, rtx_first)
  452.      FILE *outf;
  453.      rtx rtx_first;
  454. {
  455.   register rtx tmp_rtx;
  456.  
  457.   outfile = outf;
  458.   sawclose = 0;
  459.  
  460.   switch (GET_CODE (rtx_first))
  461.     {
  462.     case INSN:
  463.     case JUMP_INSN:
  464.     case CALL_INSN:
  465.     case NOTE:
  466.     case CODE_LABEL:
  467.     case BARRIER:
  468.       for (tmp_rtx = rtx_first; NULL != tmp_rtx; tmp_rtx = NEXT_INSN (tmp_rtx))
  469.     {
  470.       print_rtx (tmp_rtx);
  471.       fprintf (outfile, "\n");
  472.     }
  473.       break;
  474.  
  475.     default:
  476.       print_rtx (rtx_first);
  477.     }
  478. }
  479.  
  480. /* Subroutines of read_rtx.  */
  481.  
  482. /* Dump code after printing a message.  Used when read_rtx finds
  483.    invalid data.  */
  484.  
  485. static void
  486. dump_and_abort (expected_c, actual_c, infile)
  487.      int expected_c, actual_c;
  488.      FILE *infile;
  489. {
  490.   int c, i;
  491.  
  492.   if (expected_c >= 0)
  493.     fprintf (stderr,
  494.          "Expected character %c.  Found character %c.",
  495.          expected_c, actual_c);
  496.   fprintf (stderr, "  At file position: %ld\n", ftell (infile));
  497.   fprintf (stderr, "Following characters are:\n\t");
  498.   for (i = 0; i < 200; i++)
  499.     {
  500.       c = getc (infile);
  501.       if (EOF == c) break;
  502.       putc (c, stderr);
  503.     }
  504.   fprintf (stderr, "Aborting.\n");
  505.   abort ();
  506. }
  507.  
  508. /* Read chars from INFILE until a non-whitespace char
  509.    and return that.  Comments, both Lisp style and C style,
  510.    are treated as whitespace.
  511.    Tools such as genflags use this function.  */
  512.  
  513. int
  514. read_skip_spaces (infile)
  515.      FILE *infile;
  516. {
  517.   register int c;
  518.   while (c = getc (infile))
  519.     {
  520.       if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
  521.     ;
  522.       else if (c == ';')
  523.     {
  524.       while ((c = getc (infile)) && c != '\n') ;
  525.     }
  526.       else if (c == '/')
  527.     {
  528.       register int prevc;
  529.       c = getc (infile);
  530.       if (c != '*')
  531.         dump_and_abort ('*', c, infile);
  532.       
  533.       prevc = 0;
  534.       while (c = getc (infile))
  535.         {
  536.           if (prevc == '*' && c == '/')
  537.         break;
  538.           prevc = c;
  539.         }
  540.     }
  541.       else break;
  542.     }
  543.   return c;
  544. }
  545.  
  546. /* Read an rtx code name into the buffer STR[].
  547.    It is terminated by any of the punctuation chars of rtx printed syntax.  */
  548.  
  549. static void
  550. read_name (str, infile)
  551.      char *str;
  552.      FILE *infile;
  553. {
  554.   register char *p;
  555.   register int c;
  556.  
  557.   c = read_skip_spaces(infile);
  558.  
  559.   p = str;
  560.   while (1)
  561.     {
  562.       if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
  563.     break;
  564.       if (c == ':' || c == ')' || c == ']' || c == '"' || c == '/'
  565.       || c == '(' || c == '[')
  566.     {
  567.       ungetc (c, infile);
  568.       break;
  569.     }
  570.       *p++ = c;
  571.       c = getc (infile);
  572.     }
  573.   if (p == str)
  574.     {
  575.       fprintf (stderr, "missing name or number");
  576.       dump_and_abort (-1, -1, infile);
  577.     }
  578.  
  579.   *p = 0;
  580. }
  581.  
  582. /* Read an rtx in printed representation from INFILE
  583.    and return an actual rtx in core constructed accordingly.
  584.    read_rtx is not used in the compiler proper, but rather in
  585.    the utilities gen*.c that construct C code from machine descriptions.  */
  586.  
  587. rtx
  588. read_rtx (infile)
  589.      FILE *infile;
  590. {
  591.   register int i, j, list_counter;
  592.   RTX_CODE tmp_code;
  593.   register char *format_ptr;
  594.   /* tmp_char is a buffer used for reading decimal integers
  595.      and names of rtx types and machine modes.
  596.      Therefore, 256 must be enough.  */
  597.   char tmp_char[256];
  598.   rtx return_rtx;
  599.   register int c;
  600.   int tmp_int;
  601.  
  602.   /* Linked list structure for making RTXs: */
  603.   struct rtx_list
  604.     {
  605.       struct rtx_list *next;
  606.       rtx value;        /* Value of this node...        */
  607.     };
  608.  
  609.   c = read_skip_spaces (infile); /* Should be open paren.  */
  610.   if (c != '(')
  611.     dump_and_abort ('(', c, infile);
  612.  
  613.   read_name (tmp_char, infile);
  614.  
  615.   tmp_code = UNKNOWN;
  616.  
  617.   for (i=0; i < NUM_RTX_CODE; i++) /* @@ might speed this search up */
  618.     {
  619.       if (!(strcmp (tmp_char, GET_RTX_NAME (i))))
  620.     {
  621.       tmp_code = (RTX_CODE) i;    /* get value for name */
  622.       break;
  623.     }
  624.     }
  625.   if (tmp_code == UNKNOWN)
  626.     {
  627.       fprintf (stderr,
  628.            "Unknown rtx read in rtl.read_rtx(). Code name was %s .",
  629.            tmp_char);
  630.     }
  631.   /* (NIL) stands for an expression that isn't there.  */
  632.   if (tmp_code == NIL)
  633.     {
  634.       /* Discard the closeparen.  */
  635.       while ((c = getc (infile)) && c != ')');
  636.       return 0;
  637.     }
  638.  
  639.   return_rtx = rtx_alloc (tmp_code); /* if we end up with an insn expression
  640.                        then we free this space below.  */
  641.   format_ptr = GET_RTX_FORMAT (GET_CODE (return_rtx));
  642.  
  643.   /* If what follows is `: mode ', read it and
  644.      store the mode in the rtx.  */
  645.  
  646.   i = read_skip_spaces (infile);
  647.   if (i == ':')
  648.     {
  649.       register int k;
  650.       read_name (tmp_char, infile);
  651.       for (k = 0; k < NUM_MACHINE_MODES; k++)
  652.     if (!strcmp (GET_MODE_NAME (k), tmp_char))
  653.       break;
  654.  
  655.       PUT_MODE (return_rtx, (enum machine_mode) k );
  656.     }
  657.   else
  658.     ungetc (i, infile);
  659.  
  660.   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (return_rtx)); i++)
  661.     switch (*format_ptr++)
  662.       {
  663.     /* 0 means a field for internal use only.
  664.        Don't expect it to be present in the input.  */
  665.       case '0':
  666.     break;
  667.  
  668.       case 'e':
  669.       case 'u':
  670.     XEXP (return_rtx, i) = read_rtx (infile);
  671.     break;
  672.  
  673.       case 'E':
  674.     {
  675.       register struct rtx_list *next_rtx, *rtx_list_link;
  676.       struct rtx_list *list_rtx;
  677.  
  678.       c = read_skip_spaces (infile);
  679.       if (c != '[')
  680.         dump_and_abort ('[', c, infile);
  681.  
  682.       /* add expressions to a list, while keeping a count */
  683.       next_rtx = NULL;
  684.       list_counter = 0;
  685.       while ((c = read_skip_spaces (infile)) && c != ']')
  686.         {
  687.           ungetc (c, infile);
  688.           list_counter++;
  689.           rtx_list_link = (struct rtx_list *)
  690.         alloca (sizeof (struct rtx_list));
  691.           rtx_list_link->value = read_rtx (infile);
  692.           if (next_rtx == 0)
  693.         list_rtx = rtx_list_link;
  694.           else
  695.         next_rtx->next = rtx_list_link;
  696.           next_rtx = rtx_list_link;
  697.           rtx_list_link->next = 0;
  698.         }
  699.       /* get vector length and allocate it */
  700.       XVEC (return_rtx, i) = (list_counter
  701.                   ? rtvec_alloc (list_counter)
  702.                   : NULL);
  703.       if (list_counter > 0) 
  704.         {
  705.           next_rtx = list_rtx;
  706.           for (j = 0; j < list_counter; j++,
  707.            next_rtx = next_rtx->next)
  708.         XVECEXP (return_rtx, i, j) = next_rtx->value;
  709.         }
  710.       /* close bracket gotten */
  711.     }
  712.     break;
  713.  
  714.       case 'S':
  715.     /* 'S' is an optional string: if a closeparen follows,
  716.        just store NULL for this element.  */
  717.     c = read_skip_spaces (infile);
  718.     ungetc (c, infile);
  719.     if (c == ')')
  720.       {
  721.         XSTR (return_rtx, i) = 0;
  722.         break;
  723.       }
  724.  
  725.       case 's':
  726.     {
  727.       int saw_paren = 0;
  728.       register char *stringbuf;
  729.       int stringbufsize;
  730.  
  731.       c = read_skip_spaces (infile);
  732.       if (c == '(')
  733.         {
  734.           saw_paren = 1;
  735.           c = read_skip_spaces (infile);
  736.         }
  737.       if (c != '"')
  738.         dump_and_abort ('"', c, infile);
  739.       j = 0;
  740.       stringbufsize = 10;
  741.       stringbuf = (char *) xmalloc (stringbufsize + 1);
  742.  
  743.       while (1)
  744.         {
  745.           if (j >= stringbufsize - 4)
  746.         {
  747.           stringbufsize *= 2;
  748.           stringbuf = (char *) xrealloc (stringbuf, stringbufsize + 1);
  749.         }
  750.           stringbuf[j] = getc (infile); /* Read the string  */
  751.           if (stringbuf[j] == '\\')
  752.         {
  753.           stringbuf[j] = getc (infile);    /* Read the string  */
  754.           /* \; makes stuff for a C string constant containing
  755.              newline and tab.  */
  756.           if (stringbuf[j] == ';')
  757.             {
  758.               strcpy (&stringbuf[j], "\\n\\t");
  759.               j += 3;
  760.             }
  761.         }
  762.           else if (stringbuf[j] == '"')
  763.         break;
  764.           j++;
  765.         }
  766.  
  767.       stringbuf[j] = 0;    /* NUL terminate the string  */
  768.       stringbuf = (char *) xrealloc (stringbuf, j + 1);
  769.  
  770.       if (saw_paren)
  771.         {
  772.           c = read_skip_spaces (infile);
  773.           if (c != ')')
  774.         dump_and_abort (')', c, infile);
  775.         }
  776.       XSTR (return_rtx, i) = stringbuf;
  777.     }
  778.     break;
  779.  
  780.       case 'i':
  781.       case 'n':
  782.     read_name (tmp_char, infile);
  783.     tmp_int = atoi (tmp_char);
  784.     XINT (return_rtx, i) = tmp_int;
  785.     break;
  786.  
  787.       default:
  788.     fprintf (stderr,
  789.          "switch format wrong in rtl.read_rtx(). format was: %c.\n",
  790.          format_ptr[-1]);
  791.     fprintf (stderr, "\tfile position: %ld\n", ftell (infile));
  792.     abort ();
  793.       }
  794.  
  795.   c = read_skip_spaces (infile);
  796.   if (c != ')')
  797.     dump_and_abort (')', c, infile);
  798.  
  799.   return return_rtx;
  800. }
  801.  
  802. /* This is called once per compilation, before any rtx's are constructed.
  803.    It initializes the vector `rtx_length'.  */
  804.  
  805. void
  806. init_rtl ()
  807. {
  808.   int i;
  809.  
  810.   for (i = 0; i < NUM_RTX_CODE; i++)
  811.     rtx_length[i] = strlen (rtx_format[i]);
  812.  
  813.   /* Make CONST_DOUBLE bigger, if real values are bigger than
  814.      it normally expects to have room for.
  815.      Note that REAL_VALUE_TYPE is not defined by default,
  816.      since tree.h is not included.  But the default dfn as `double'
  817.      would do no harm.  */
  818. #ifdef REAL_VALUE_TYPE
  819.   i = sizeof (REAL_VALUE_TYPE) / sizeof (rtunion) + 2;
  820.   if (rtx_length[(int) CONST_DOUBLE] < i)
  821.     {
  822.       char *s = (char *) malloc (i + 1);
  823.       rtx_length[(int) CONST_DOUBLE] = i;
  824.       rtx_format[(int) CONST_DOUBLE] = s;
  825.       *s++ = 'e';
  826.       *s++ = '0';
  827.       /* Set the GET_RTX_FORMAT of CONST_DOUBLE to a string
  828.      of as many `i's as we now have elements.  */
  829.       for (i = 0; i < rtx_length[(int) CONST_DOUBLE]; i++)
  830.     *s++ = 'i';
  831.       *s++ = 0;
  832.     }
  833. #endif
  834. }
  835.